import type { UniqueIdentifier } from '@dnd-kit/core';
import { arrayMove } from '@dnd-kit/sortable';

import type { FlattenedItem, TreeItem, TreeItems } from './types';

export const iOS = /iPad|iPhone|iPod/.test(navigator.userAgent);

function getDragDepth(offset: number, indentationWidth: number) {
  return Math.round(offset / indentationWidth);
}

// 获取预测数据
export function getProjection(
  items: FlattenedItem[],
  activeId: UniqueIdentifier,
  overId: UniqueIdentifier,
  dragOffset: number,
  indentationWidth: number
) {

  const overItemIndex = items.findIndex(({ id }) => id === overId);
  const activeItemIndex = items.findIndex(({ id }) => id === activeId);

  const activeItem = items[activeItemIndex];
  if (!activeItem) {
    return null;
  }
  const newItems = arrayMove(items, activeItemIndex, overItemIndex);
  const previousItem = newItems[overItemIndex - 1];
  const nextItem = newItems[overItemIndex + 1];
  const dragDepth = getDragDepth(dragOffset, indentationWidth); // 拖动的层级
  const projectedDepth = activeItem.depth + dragDepth; // 最终的层级
  const maxDepth = getMaxDepth({ previousItem }); // 最大层级
  const minDepth = getMinDepth({ nextItem }); // 最小层级
  let depth = projectedDepth; // 必须在范围内

  if (projectedDepth >= maxDepth) {
    depth = maxDepth;
  } else if (projectedDepth < minDepth) {
    depth = minDepth;
  }

  // 获取parentId
  function getParentId() {
    if (depth === 0 || !previousItem) {
      return null;
    }

    // 与前一个元素同层级，取前一个元素的parentId
    if (depth === previousItem.depth) {
      return previousItem.parentId;
    }

    // 比前一个元素的层级深，取前一个元素的id作为parentId
    if (depth > previousItem.depth) {
      return previousItem.id;
    }

    // 比前一个元素的层级小，计算层级
    const newParent = newItems
      .slice(0, overItemIndex)
      .reverse()
      .find((item) => item.depth === depth)?.parentId;

    return newParent ?? null;
  }

  return { depth, maxDepth, minDepth, parentId: getParentId() };

}

function getMaxDepth({ previousItem }: { previousItem: FlattenedItem }) {


  // 有下一级
  if (previousItem) {
    return ['if', 'elseif', 'else', 'while', 'times', 'forEach'].includes(previousItem.cmd) ? previousItem.depth + 1 : previousItem.depth;
  }

  return 0;
}

function getMinDepth({ nextItem }: { nextItem: FlattenedItem }) {
  if (nextItem) {
    return nextItem.depth;
  }

  return 0;
}

// 展开树，读取源数据时使用
export function flattenTree(items: TreeItems): FlattenedItem[] {
  let seq = 0;
  const flatten = (
    items: TreeItems,
    parentId: UniqueIdentifier | null = null,
    depth = 0,
  ): FlattenedItem[] => {
    return items.reduce<FlattenedItem[]>((acc, item, index) => {
      // 如果id为空，则生成一个随机id

      item.id = item.id ?? window.crypto.randomUUID()
      seq++;

      const {
        children,
        ...others
      } = item

      return [
        ...acc,
        { ...others, parentId, depth, index, seq },
        ...flatten(children || [], item.id, depth + 1),
      ];
    }, []);
  }
  return flatten(items);
}

// 构建树，保存为源数据时使用
export function buildTree(flattenedItems: FlattenedItem[]): TreeItems {
  const root: TreeItem = { id: 'root', cmd: '', target: '', value: '', children: [] };
  const nodes: Record<string, TreeItem> = { [root.id]: root };
  const items = flattenedItems.map((item) => ({ ...item, children: [] }));

  for (const item of items) {
    const { id, children, ...props } = item;
    const parentId = item.parentId ?? root.id;
    const parent = nodes[parentId] ?? findItem(items, parentId);
    if (!parent.children) {
      parent.children = []
    }
    nodes[id] = { id, children, ...props };
    parent.children.push(item);
  }

  return root.children || [];
}
// 查找item
export function findItem(items: TreeItem[], itemId: UniqueIdentifier) {
  return items.find(({ id }) => id === itemId);
}
// 查找item深度
export function findItemDeep(
  items: TreeItems,
  itemId: UniqueIdentifier
): TreeItem | undefined {
  for (const item of items) {
    const { id, children } = item;

    if (id === itemId) {
      return item;
    }

    if (children?.length) {
      const child = findItemDeep(children, itemId);

      if (child) {
        return child;
      }
    }
  }

  return undefined;
}
// 删除item
export function removeItem(items: TreeItems, id: UniqueIdentifier) {
  const newItems = [];

  for (const item of items) {
    if (item.id === id) {
      continue;
    }

    if (item.children?.length) {
      item.children = removeItem(item.children, id);
    }

    newItems.push(item);
  }

  return newItems;
}
// 设置item属性
export function setProperty<T extends keyof TreeItem>(
  items: TreeItems,
  id: UniqueIdentifier,
  property: T,
  setter: (value: TreeItem[T]) => TreeItem[T]
) {
  return items.map((item: TreeItem): TreeItem => {
    if (item.id === id) {
      item[property] = setter(item[property]);
    }
    return {
      ...item,
      children: setProperty(item.children || [], id, property, setter)
    }
  });
}
// 后代节点数量
function countChildren(items: TreeItem[], count = 0): number {
  return items.reduce((acc, { children }) => {
    if (children?.length) {
      return countChildren(children, acc + 1);
    }

    return acc + 1;
  }, count);
}
// 获取后代节点数量
export function getChildCount(items: TreeItems, id: UniqueIdentifier) {
  const item = findItemDeep(items, id);

  return item ? countChildren(item.children || []) : 0;
}
// 移除后代节点
export function removeChildrenOf(
  items: FlattenedItem[],
  ids: UniqueIdentifier[]
) {
  const excludeParentIds = [...ids];

  return items.filter((item) => {
    // if (item.cmd === 'end') {
    //   return false
    // }
    if (item.parentId && excludeParentIds.includes(item.parentId)) {
      if (item.children?.length) {
        excludeParentIds.push(item.id);
      }
      return false;
    }

    return true;
  });
}
